home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 140
/
Gekkan Dennou Club - 2000.1 Vol. 140 (Japan).7z
/
Gekkan Dennou Club - 2000.1 Vol. 140 (Japan) (Track 1).bin
/
tools
/
dshell
/
dsh333bs.lzh
/
dshell.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-05
|
8KB
|
370 lines
/*
dshell v3
ファイル読込・展開用バッファ管理等
*/
#include "dsh.h"
#define STACK_MARGIN (4*1024) // ネスト限界を決めるスタック残り容量
/*
テキストの“要nM”チェック
*/
static void
checkMemory(void *head)
{
void *p;
int n;
char temp[64];
n = MALLOC(MALLOC(-1) & 0x00ffffff);
if (n < 0)
return;
MFREE(n);
p = (void *)n - 0x10;
if (p <= (void *)0x100000)
return;
for (n = 0x200000; p > (void *)n; n += n)
;
n >>= 1;
p = head - 0x10;
if (p <= (void *)n) {
ushort shiftKeys;
w_open();
sprintf(temp, "%dMB 境界を越えました", n >> 20);
w_mes(0, temp);
shiftKeys = B_SFTSNS();
if (!(shiftKeys & LED_CODEIN) || !(shiftKeys & (LED_ROMA | LED_KANA)))
w_wait(99);
}
}
static void
fileNotFound(const uchar *fname)
{
char temp[96];
const uchar *p = fname;
uchar c;
while ((c = *p++) >= '\x20')
;
if (*--p == '\0')
sprintf(temp, "ファイル(%.32s)が見つかりません", fname);
else
sprintf(temp, "ファイル名に誤りがあります", fname);
dabort(temp);
}
static void
cut_free(int cut_no)
{
for (; cut_no < CUT_MAX && cut[cut_no].fname != NULL; cut_no++) {
cut[cut_no].fname = NULL;
if (cut[cut_no].ptr != NULL) {
if (MFREE(cut[cut_no].ptr))
d_mfree();
}
}
}
static void
freeFont(int fontNo)
{
for (; fontNo < FONTMAX && font16[fontNo].fname != NULL; fontNo++) {
font16[fontNo].fname = NULL;
if (font16[fontNo].pat != NULL) {
if (MFREE(font16[fontNo].pat))
d_mfree();
}
}
}
/*
ファイル読込・展開・ポインタテーブル用意
テキストデータ展開用+行ポインタテーブル用領域確保
テキストデータ展開と行ポインタ展開とで双方から食っていき
行ポインタテーブルは逆順から正順に戻しつつ展開後のテキストの
後ろに移動。余った部分はsetblockで解放。
------- ================== ================== ==================
↑ 大域変数待避領域 大域変数待避領域 大域変数待避領域
------------------ ------------------ ------------------
テキスト展開領域 展開後のテキスト 展開後のテキスト
MALLOCで +------- : :
----------+ ------------------ ------------------
確保した ↓ 行ポインタ(正順)
-> (余った領域) -> :
ブロック ↑ +----- ------------------ ------------------
-----------+ : (SETBLOCKで解放)
行ポインタ(逆順) 行ポインタ(逆順) :
------------------ ------------------ :
↓ ファイル読込領域 ファイル読込領域 :
------- ================== ================== ==================
*/
static inline int
dshell_sub(char *fname)
{
typedef struct {
// 親テキストについての情報待避用
char *filename;
int lp;
int lpmx;
uchar **lhp;
int curLine;
int exeLine;
ushort textColor;
ushort bgColor;
CUT *bgCut;
int Cut_Begin;
int curFontNo;
SHELLVAR *sysVar;
short defGMODE;
// テキスト本体
uchar contents[0];
} TEXTHEAD;
#define hp ((TEXTHEAD *)ptr)
void *ptr, *ptr2;
int n;
static uchar noCtrlCharFlag;
w_open();
w_load();
noCtrlCharFlag = FALSE;
if (*fname == '!') {
fname++;
noCtrlCharFlag = TRUE;
}
{
FILE *fp;
int size;
fp = fopen(fname, "rb");
if (fp == NULL || (n = dfilelength(fileno(fp))) < 0) {
fileNotFound(fname);
return -1;
}
do {
/*
テキストデータ展開用+行ポインタテーブル用領域確保
*/
size = MALLOC(-1) & 0x00ffffff; /* まず空きサイズを知る */
/* ファイル読み込み分なかったら帰る(仕様変更予定あり) */
#define MINSIZ 512 // 若干のゆとり
if (size <= n + MINSIZ) {
d_mem();
fclose(fp);
return -1;
}
/*
で、とりあえずめいっぱい確保する
*/
ptr = (void *)MALLOC(size);
} while ((int)ptr < 0);
/*
テキストデータ読み込み用バッファ先頭
=仮の行ポインタテーブル末尾を決める
*/
ptr2 = (void *)(((int)ptr + size - (n + 2)) & -4); // +2 は終端コードの分
if (n > 0) {
if (fread(ptr2, sizeof(char), n, fp) != n) {
d_read(); /* 'ファイル読み込みエラー' */
if (MFREE(ptr)) {
d_mfree();
}
fclose(fp);
return -1;
}
}
fclose(fp);
*(uchar *)(ptr2 + n) = 0x1a; /* 終端コード */
*(uchar *)(ptr2 + n + 1) = 0x1a; // 末尾に2バイト文字の第1バイトがあった場合の予備
}
hp->filename = filename;
hp->lp = lp;
hp->lpmx = lpmx;
hp->lhp = lhp;
hp->curLine = curLine;
hp->exeLine = exeLine;
hp->textColor = tx_col[3];
hp->bgColor = gr_col[0];
hp->bgCut = bgCut;
hp->Cut_Begin = Cut_Begin;
hp->curFontNo = curFontNo;
hp->sysVar = sysVarListHead;
hp->defGMODE = defGMODE;
{
short bmid; /* bookmark id 保存(メモ)用 */
unsigned short tcrc; /* 保持用 */
/*
表示用にテキストを整理
*/
if (n > 4*1024) {
w_mes(0, "ファイルの整理中です");
w_mes(1, "しばらくお待ち下さい");
}
tcrc = calc_crc(0, ptr2, n);
ptr2 = sort(ptr + offsetof(TEXTHEAD, contents), ptr2, fname, n, noCtrlCharFlag, ptr);
if (ptr2 == NULL) {
d_mem();
if (MFREE(ptr)) {
d_mfree();
}
return -1;
}
if (SETBLOCK(ptr, ptr2 - ptr)) {
w_open();
w_mes(0, "メモリブロックのサイズ変更ができません");
w_mes(2, "全ての処理を中断します"); /* 処理を続行するとアブナイようなので… */
w_wait(0);
dsh_abort(1);
}
Cut_Begin = cut_job_read(Cut_Begin);
curFontNo = readFontFile(curFontNo);
/*
現読込中ファイルだったら登録関係は一切せず、
新規表示開始位置は0
*/
bmid = crc_to_IMAno(tcrc);
if (bmid >= 0) {
lp = 0;
bmid = -1; /* bmid は兼フラグ */
} else {
bmid = crc_to_KAKOno(tcrc);
if (bmid != -1) {
lp = get_ln(bmid);
if (lp < 0) {
lp = 0; /* errorなんで */
bmid = -1;
}
} else {
bmid = regist_IMAmark(tcrc); /* errorだった場合登録せず(-1が返るので登録関係はいじらない結果になる。でもまず起きないエラー) */
set_fnm_to_mark(bmid, fname);
lp = 0;
}
}
/*
閲覧
*/
filename = fname;
defGMODE = GMODE;
if (debugMode)
checkMemory(ptr);
if (GMODE == 0 && hp->bgCut != bgCut)
resetBG();
n = get_event();
if (bmid >= 0) {
put_ln(bmid, lp);
IMAtoKAKO(bmid);
set_fnm_to_mark(bmid, NULL);
}
resetBgFlag = (GMODE > 0 || hp->bgCut != bgCut);
}
filename = hp->filename;
lp = hp->lp;
lpmx = hp->lpmx;
lhp = hp->lhp;
curLine = hp->curLine;
exeLine = hp->exeLine;
tx_col[3] = hp->textColor;
gr_col[0] = hp->bgColor;
bgCut = hp->bgCut;
Cut_Begin = hp->Cut_Begin;
curFontNo = hp->curFontNo;
defGMODE = hp->defGMODE;
/*
オシマイの処理
*/
/* cut ↓:領域開放 */
cut_free(Cut_Begin);
/* cut ↑ */
freeFont(curFontNo);
freeMenu(ptr);
while (hp->sysVar != sysVarListHead) {
SHELLVAR *vp = sysVarListHead;
sysVarListHead = vp->next;
free(vp);
}
if (MFREE(ptr)) {
d_mfree();
}
return n;
}
/*
ファイル読込ネスト管理
(global) nest:呼び出されレベル(0なら一番初めの呼び出し:復帰不可)
*/
void
dshell(char *fname)
{
static int n;
if (getSp() - _SSTA < STACK_MARGIN) {
w_open();
w_mes(0, "作業領域がいっぱいです");
w_mes(2, "これ以上読み込めません");
w_mes(3, "(STACK OVERFLOW 回避措置)"); /* そのうちスタック使わんように改造するか…? */
w_wait(0);
w_close();
return;
}
nest++;
while ((n = dshell_sub(fname)) > 0) {
/*
登録キーによるエディタの起動
*/
char *p;
char *temp = malloc(256);
if (temp == NULL)
break;
if ((p = getenv("DSHELL_EDITOR")) != NULL || (p = getenv("EDITOR")) != NULL) {
char *q = strchr(p, '#');
if (q == NULL) {
strcpy(temp, p);
} else {
strncpy(temp, p, q - p);
itoa(n, temp + (q - p), 10);
strcat(temp, ++q);
}
strcat(temp, " ");
strcat(temp, fname + (*fname == '!'));
nouse_fnk();
C_WIDTH(0);
dexec(temp, DEX_FKON);
}
free(temp);
}
nest--;
}